//
//  IFlyRealTimeASRExample.swift
//  GLUZSwift
//
//  Created by AI Assistant on 2024/12/19.
//  Copyright © 2024 考拉🐨. All rights reserved.
//

import UIKit
import AVFoundation

// MARK: - 实时语音转写使用示例
class IFlyRealTimeASRExample: UIViewController {
    
    // MARK: - UI元素
    private lazy var resultLabel: UILabel = {
        let label = UILabel()
        label.text = "识别结果将显示在这里..."
        label.textColor = .black
        label.font = UIFont.systemFont(ofSize: 16)
        label.numberOfLines = 0
        label.textAlignment = .left
        label.backgroundColor = .systemGray6
        label.layer.cornerRadius = 8
        label.layer.masksToBounds = true
        return label
    }()
    
    private lazy var startButton: UIButton = {
        let button = UIButton(type: .system)
        button.setTitle("开始识别", for: .normal)
        button.setTitleColor(.white, for: .normal)
        button.backgroundColor = .systemBlue
        button.layer.cornerRadius = 8
        button.titleLabel?.font = UIFont.systemFont(ofSize: 16, weight: .medium)
        button.addTarget(self, action: #selector(startButtonTapped), for: .touchUpInside)
        return button
    }()
    
    private lazy var stopButton: UIButton = {
        let button = UIButton(type: .system)
        button.setTitle("停止识别", for: .normal)
        button.setTitleColor(.white, for: .normal)
        button.backgroundColor = .systemRed
        button.layer.cornerRadius = 8
        button.titleLabel?.font = UIFont.systemFont(ofSize: 16, weight: .medium)
        button.addTarget(self, action: #selector(stopButtonTapped), for: .touchUpInside)
        return button
    }()
    
    private lazy var cancelButton: UIButton = {
        let button = UIButton(type: .system)
        button.setTitle("取消识别", for: .normal)
        button.setTitleColor(.white, for: .normal)
        button.backgroundColor = .systemGray
        button.layer.cornerRadius = 8
        button.titleLabel?.font = UIFont.systemFont(ofSize: 16, weight: .medium)
        button.addTarget(self, action: #selector(cancelButtonTapped), for: .touchUpInside)
        return button
    }()
    
    private lazy var languageSegmentedControl: UISegmentedControl = {
        let control = UISegmentedControl(items: ["中文", "俄文"])
        control.selectedSegmentIndex = 0
        control.addTarget(self, action: #selector(languageChanged), for: .valueChanged)
        return control
    }()
    
    private lazy var statusLabel: UILabel = {
        let label = UILabel()
        label.text = "准备就绪"
        label.textColor = .systemBlue
        label.font = UIFont.systemFont(ofSize: 14)
        label.textAlignment = .center
        return label
    }()
    
    private lazy var volumeLabel: UILabel = {
        let label = UILabel()
        label.text = "音量: 0"
        label.textColor = .systemGreen
        label.font = UIFont.systemFont(ofSize: 14)
        label.textAlignment = .center
        return label
    }()
    
    private lazy var scrollView: UIScrollView = {
        let scrollView = UIScrollView()
        scrollView.showsVerticalScrollIndicator = true
        scrollView.alwaysBounceVertical = true
        return scrollView
    }()
    
    private lazy var contentView: UIView = {
        let view = UIView()
        return view
    }()
    
    // MARK: - 属性
    private var currentResult = ""
    private var lastCompleteResult = "" // 存储上一次完整的结果
    private var audioEngine: AVAudioEngine?
    private var inputNode: AVAudioInputNode?
    private var audioFormat: AVAudioFormat?
    
    // MARK: - 生命周期
    override func viewDidLoad() {
        super.viewDidLoad()
        setupUI()
        setupRealTimeASR()
        setupAudioEngine()
    }
    
    deinit {
        stopAudioEngine()
        IFlyRealTimeASRManager.shared.cancelRealTimeASR()
    }
    
    // MARK: - 私有方法
    private func setupUI() {
        title = "实时语音转写示例"
        view.backgroundColor = .systemBackground
        
        // 添加子视图
        view.addSubview(scrollView)
        scrollView.addSubview(contentView)
        contentView.addSubview(resultLabel)
        contentView.addSubview(startButton)
        contentView.addSubview(stopButton)
        contentView.addSubview(cancelButton)
        contentView.addSubview(languageSegmentedControl)
        contentView.addSubview(statusLabel)
        contentView.addSubview(volumeLabel)
        
        // 设置约束
        setupConstraints()
        
        // 设置按钮状态
        updateButtonStates()
    }
    
    private func setupConstraints() {
        scrollView.translatesAutoresizingMaskIntoConstraints = false
        contentView.translatesAutoresizingMaskIntoConstraints = false
        resultLabel.translatesAutoresizingMaskIntoConstraints = false
        startButton.translatesAutoresizingMaskIntoConstraints = false
        stopButton.translatesAutoresizingMaskIntoConstraints = false
        cancelButton.translatesAutoresizingMaskIntoConstraints = false
        languageSegmentedControl.translatesAutoresizingMaskIntoConstraints = false
        statusLabel.translatesAutoresizingMaskIntoConstraints = false
        volumeLabel.translatesAutoresizingMaskIntoConstraints = false
        
        NSLayoutConstraint.activate([
            // ScrollView约束
            scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
            scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
            
            // ContentView约束
            contentView.topAnchor.constraint(equalTo: scrollView.topAnchor),
            contentView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),
            contentView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor),
            contentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
            contentView.widthAnchor.constraint(equalTo: scrollView.widthAnchor),
            
            // 结果标签约束
            resultLabel.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 20),
            resultLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20),
            resultLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20),
            resultLabel.heightAnchor.constraint(greaterThanOrEqualToConstant: 120),
            
            // 语言选择器约束
            languageSegmentedControl.topAnchor.constraint(equalTo: resultLabel.bottomAnchor, constant: 20),
            languageSegmentedControl.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20),
            languageSegmentedControl.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20),
            languageSegmentedControl.heightAnchor.constraint(equalToConstant: 32),
            
            // 状态标签约束
            statusLabel.topAnchor.constraint(equalTo: languageSegmentedControl.bottomAnchor, constant: 20),
            statusLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20),
            statusLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20),
            statusLabel.heightAnchor.constraint(equalToConstant: 20),
            
            // 音量标签约束
            volumeLabel.topAnchor.constraint(equalTo: statusLabel.bottomAnchor, constant: 10),
            volumeLabel.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20),
            volumeLabel.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20),
            volumeLabel.heightAnchor.constraint(equalToConstant: 20),
            
            // 开始按钮约束
            startButton.topAnchor.constraint(equalTo: volumeLabel.bottomAnchor, constant: 30),
            startButton.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20),
            startButton.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20),
            startButton.heightAnchor.constraint(equalToConstant: 50),
            
            // 停止按钮约束
            stopButton.topAnchor.constraint(equalTo: startButton.bottomAnchor, constant: 15),
            stopButton.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20),
            stopButton.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20),
            stopButton.heightAnchor.constraint(equalToConstant: 50),
            
            // 取消按钮约束
            cancelButton.topAnchor.constraint(equalTo: stopButton.bottomAnchor, constant: 15),
            cancelButton.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20),
            cancelButton.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -20),
            cancelButton.heightAnchor.constraint(equalToConstant: 50),
            cancelButton.bottomAnchor.constraint(lessThanOrEqualTo: contentView.bottomAnchor, constant: -20)
        ])
    }
    
    private func setupRealTimeASR() {
        // 设置代理
        IFlyRealTimeASRManager.shared.delegate = self
        
        // 设置初始语言
        IFlyRealTimeASRManager.shared.setLanguage(.chinese)
    }
    
    private func setupAudioEngine() {
        audioEngine = AVAudioEngine()
        inputNode = audioEngine?.inputNode
        
        // 获取硬件输入格式
        guard let inputFormat = inputNode?.outputFormat(forBus: 0) else {
            print("❌ 无法获取输入格式")
            return
        }
        
        print("🔊 硬件输入格式: \(inputFormat)")
        
        // 创建目标格式：16kHz, 16bit, 单声道
        audioFormat = AVAudioFormat(
            commonFormat: .pcmFormatInt16,
            sampleRate: 16000,
            channels: 1,
            interleaved: false
        )
        
        guard let audioFormat = audioFormat else {
            print("❌ 创建音频格式失败")
            return
        }
        
        // 创建格式转换器
        guard let converter = AVAudioConverter(from: inputFormat, to: audioFormat) else {
            print("❌ 创建音频转换器失败")
            return
        }
        
        // 安装音频处理节点，使用硬件格式
        inputNode?.installTap(onBus: 0, bufferSize: 1024, format: inputFormat) { [weak self] buffer, _ in
            self?.processAudioBuffer(buffer, converter: converter)
        }
    }
    
    private func processAudioBuffer(_ buffer: AVAudioPCMBuffer, converter: AVAudioConverter) {
        guard let audioFormat = audioFormat else {
            return
        }
        
        // 创建输出缓冲区
        let outputBuffer = AVAudioPCMBuffer(pcmFormat: audioFormat, frameCapacity: AVAudioFrameCount(Double(buffer.frameLength) * audioFormat.sampleRate / buffer.format.sampleRate))!
        
        var error: NSError?
        let status = converter.convert(to: outputBuffer, error: &error) { _, outStatus in
            outStatus.pointee = .haveData
            return buffer
        }
        
        guard status != .error, error == nil else {
            print("❌ 音频格式转换失败: \(error?.localizedDescription ?? "未知错误")")
            return
        }
        
        // 获取转换后的音频数据
        guard let channelData = outputBuffer.int16ChannelData else {
            return
        }
        
        let channelDataValue = channelData.pointee
        let channelDataValueArray = stride(from: 0, to: Int(outputBuffer.frameLength), by: outputBuffer.stride).map { channelDataValue[$0] }
        
        // 转换为Data
        let audioData = Data(bytes: channelDataValueArray, count: channelDataValueArray.count * MemoryLayout<Int16>.size)
        
        // 发送音频数据到实时语音转写
        IFlyRealTimeASRManager.shared.sendAudioData(audioData)
        
        // 计算音量（可选）
        let volume = calculateVolume(from: channelDataValueArray)
        DispatchQueue.main.async { [weak self] in
            self?.volumeLabel.text = "音量: \(volume)"
        }
    }
    
    private func calculateVolume(from samples: [Int16]) -> Int {
        guard !samples.isEmpty else { return 0 }
        
        // 使用 Int64 避免溢出
        let sum: Int64 = samples.reduce(0) { Int64($0) + Int64(abs($1)) }
        let average = sum / Int64(samples.count)
        return min(Int(average / 1000), 100) // 转换为0-100的范围
    }
    
    private func startAudioEngine() {
        guard let audioEngine = audioEngine else { return }
        
        do {
            try audioEngine.start()
            print("✅ 音频引擎启动成功")
        } catch {
            print("❌ 音频引擎启动失败: \(error.localizedDescription)")
        }
    }
    
    private func stopAudioEngine() {
        audioEngine?.stop()
        inputNode?.removeTap(onBus: 0)
        print("🔊 音频引擎已停止")
    }
    
    private func updateButtonStates() {
        let isListening = IFlyRealTimeASRManager.shared.isListening
        
        startButton.isEnabled = !isListening
        stopButton.isEnabled = isListening
        cancelButton.isEnabled = isListening
        
        startButton.alpha = isListening ? 0.5 : 1.0
        stopButton.alpha = isListening ? 1.0 : 0.5
        cancelButton.alpha = isListening ? 1.0 : 0.5
    }
    
    // MARK: - 按钮事件
    @objc private func startButtonTapped(_ sender: UIButton) {
        // 清空之前的结果
        currentResult = ""
        lastCompleteResult = ""
        resultLabel.text = "正在识别..."
        
        // 开始识别
        let success = IFlyRealTimeASRManager.shared.startRealTimeASR()
        if success {
            statusLabel.text = "正在识别中..."
            startAudioEngine()
            updateButtonStates()
        } else {
            statusLabel.text = "开始识别失败"
        }
    }
    
    @objc private func stopButtonTapped(_ sender: UIButton) {
        IFlyRealTimeASRManager.shared.stopRealTimeASR()
        stopAudioEngine()
        statusLabel.text = "正在处理结果..."
        updateButtonStates()
    }
    
    @objc private func cancelButtonTapped(_ sender: UIButton) {
        IFlyRealTimeASRManager.shared.cancelRealTimeASR()
        stopAudioEngine()
        statusLabel.text = "已取消识别"
        resultLabel.text = "识别已取消"
        updateButtonStates()
    }
    
    @objc private func languageChanged(_ sender: UISegmentedControl) {
        let language: IFlyRealTimeASRLanguage = sender.selectedSegmentIndex == 0 ? .chinese : .russian
        IFlyRealTimeASRManager.shared.setLanguage(language)
        statusLabel.text = "已切换到\(language.displayName)"
    }
}

// MARK: - IFlyRealTimeASRDelegate
extension IFlyRealTimeASRExample: IFlyRealTimeASRDelegate {
    
    func realTimeASRDidReceiveResult(_ result: String, isLast: Bool) {
        print("🔊 收到识别结果: \(result), 是否最后结果: \(isLast)")
        
        if isLast {
            // 如果是最后结果，直接使用这个结果
            currentResult = lastCompleteResult + result
            lastCompleteResult = currentResult
        } else {
            // 如果是中间结果，显示完整结果 + 当前中间结果
            currentResult = lastCompleteResult + result
        }
        
        // 更新UI
        DispatchQueue.main.async { [weak self] in
            self?.resultLabel.text = self?.currentResult
        }
    }
    
    func realTimeASRDidComplete(_ error: Error?) {
        DispatchQueue.main.async { [weak self] in
            if let error = error {
                self?.statusLabel.text = "识别失败: \(error.localizedDescription)"
                self?.resultLabel.text = "识别失败"
            } else {
                self?.statusLabel.text = "识别完成"
            }
            self?.updateButtonStates()
        }
    }
    
    func realTimeASRDidBegin() {
        DispatchQueue.main.async { [weak self] in
            self?.statusLabel.text = "正在录音..."
        }
    }
    
    func realTimeASRDidEnd() {
        DispatchQueue.main.async { [weak self] in
            self?.statusLabel.text = "录音结束，正在识别..."
        }
    }
    
    func realTimeASRConnectionStateChanged(_ isConnected: Bool) {
        DispatchQueue.main.async { [weak self] in
            self?.statusLabel.text = isConnected ? "已连接" : "连接断开"
        }
    }
    
    func realTimeASRDidFail(_ error: Error) {
        DispatchQueue.main.async { [weak self] in
            self?.statusLabel.text = "识别失败: \(error.localizedDescription)"
            self?.resultLabel.text = "识别失败"
            self?.updateButtonStates()
        }
    }
}

// MARK: - 简单使用示例
extension IFlyRealTimeASRExample {
    
    /// 简单的实时语音转写使用示例
    func simpleUsageExample() {
        // 1. 设置代理
        IFlyRealTimeASRManager.shared.delegate = self
        
        // 2. 设置语言
        IFlyRealTimeASRManager.shared.setLanguage(.chinese)
        
        // 3. 开始识别
        IFlyRealTimeASRManager.shared.startRealTimeASR()
        
        // 4. 发送音频数据（需要从音频采集设备获取PCM数据）
        // let audioData = getPCMDataFromMicrophone()
        // IFlyRealTimeASRManager.shared.sendAudioData(audioData)
        
        // 5. 停止识别
        // IFlyRealTimeASRManager.shared.stopRealTimeASR()
    }
    
    /// 从音频文件进行实时转写示例
    func transcribeAudioFile(_ filePath: String) {
        guard let audioFile = try? AVAudioFile(forReading: URL(fileURLWithPath: filePath)) else {
            print("❌ 无法打开音频文件: \(filePath)")
            return
        }
        
        // 设置音频格式
        let audioFormat = AVAudioFormat(
            commonFormat: .pcmFormatInt16,
            sampleRate: 16000,
            channels: 1,
            interleaved: false
        )
        
        guard let format = audioFormat else {
            print("❌ 创建音频格式失败")
            return
        }
        
        // 开始识别
        IFlyRealTimeASRManager.shared.startRealTimeASR()
        
        // 读取音频文件并发送数据
        let bufferSize: AVAudioFrameCount = 1024
        let buffer = AVAudioPCMBuffer(pcmFormat: format, frameCapacity: bufferSize)!
        
        while audioFile.framePosition < audioFile.length {
            do {
                try audioFile.read(into: buffer)
                
                // 获取音频数据
                guard let channelData = buffer.int16ChannelData else { continue }
                let channelDataValue = channelData.pointee
                let channelDataValueArray = stride(from: 0, to: Int(buffer.frameLength), by: buffer.stride).map { channelDataValue[$0] }
                
                // 转换为Data
                let audioData = Data(bytes: channelDataValueArray, count: channelDataValueArray.count * MemoryLayout<Int16>.size)
                
                // 发送音频数据
                IFlyRealTimeASRManager.shared.sendAudioData(audioData)
                
                // 模拟实时发送（每40ms发送一次）
                Thread.sleep(forTimeInterval: 0.04)
                
            } catch {
                print("❌ 读取音频文件失败: \(error.localizedDescription)")
                break
            }
        }
        
        // 停止识别
        IFlyRealTimeASRManager.shared.stopRealTimeASR()
    }
}
